go to index

Underfitting and Overfitting

read time 9 min read
Kaggle Intro Machine Learning

Underfitting and Overfitting

在这一步结束时,你将理解欠拟合和过拟合的概念,并能够将这些理念应用到使你的模型更准确

Experimenting With Different Models

既然你已经有了可靠的方法来衡量模型的准确性,你就可以尝试不同的模型,看看哪个能提供最佳的预测。但是,你有哪些模型的替代选项呢?

你可以在scikit-learn的文档中看到,决策树模型有很多选项(比你长时间需要的还要多)。最重要的选项决定了树的深度。回想一下本课程的第一课,树的深度是衡量它在做出预测之前进行多少次分割的指标。这是一个相对较浅的树。

Depth 2 Tree

在实践中,一棵树在顶层(所有房屋)和叶子节点之间有10次分割并不罕见。随着树变得更深,数据集被切割成包含更少房屋的叶子。如果一棵树只有1次分割,它会将数据分成2组。如果每组再次分割,我们将得到4组房屋。再次分割这些组将创建8组。如果我们通过在每个级别添加更多分割来持续将组数翻倍,到第10级时我们将有[2^{10}]组房屋。那是1024个叶子。

当我们将房屋分配给许多叶子时,每个叶子中的房屋数量也会减少。叶子中房屋很少将使得预测值非常接近这些房屋的实际值,但它们可能对新数据做出非常不可靠的预测(因为每个预测仅基于少数房屋)。

这是一种称为**overfitting(过拟合)**的现象,模型几乎完美地匹配训练数据,但在验证和其他新数据上表现不佳。另一方面,如果我们使树非常浅,它就不会将房屋分成非常不同的组。

在极端情况下,如果一棵树只将房屋分成2或4组,每个组仍然有各种各样的房屋。对于大多数房屋来说,结果预测可能相差很远,即使在训练数据中也是如此(出于同样的原因,在验证中也会很糟糕)。当模型未能捕捉数据中的重要区别和模式,以至于即使在训练数据上也表现不佳时,这被称为underfitting(欠拟合)

由于我们关心新数据的准确性,我们从验证数据中估计这一点,我们希望在欠拟合和过拟合之间找到最佳点。在下面的图表中,我们希望找到(红色)验证曲线的最低点。

underfitting_overfitting

Example

控制树的深度有几种替代方法,许多方法允许树中的某些路径比其他路径更深。但是,max_leaf_nodes 参数提供了一种非常合理的控制过拟合与欠拟合的方法。我们允许模型创建的叶子越多,我们就越多地从上述图表中的欠拟合区域移动到过拟合区域。

我们可以使用一个效用函数(utility function)来帮助比较不同max_leaf_nodes值的MAE(平均绝对误差)得分:

python
from sklearn.metrics import mean_absolute_error
from sklearn.tree import DecisionTreeRegressor

def get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y):
    model = DecisionTreeRegressor(max_leaf_nodes=max_leaf_nodes, random_state=0)
    model.fit(train_X, train_y)
    preds_val = model.predict(val_X)
    mae = mean_absolute_error(val_y, preds_val)
    return(mae)

使用您已经看到(并且已经编写过)的代码将数据加载到train_X、val_X、train_y和val_y中。

python
# Data Loading Code Runs At This Point
import pandas as pd
    
# Load data
melbourne_file_path = '../input/melbourne-housing-snapshot/melb_data.csv'
melbourne_data = pd.read_csv(melbourne_file_path) 
# Filter rows with missing values
filtered_melbourne_data = melbourne_data.dropna(axis=0)
# Choose target and features
y = filtered_melbourne_data.Price
melbourne_features = ['Rooms', 'Bathroom', 'Landsize', 'BuildingArea', 
                        'YearBuilt', 'Lattitude', 'Longtitude']
X = filtered_melbourne_data[melbourne_features]

from sklearn.model_selection import train_test_split

# split data into training and validation data, for both features and target
train_X, val_X, train_y, val_y = train_test_split(X, y,random_state = 0)

我们可以使用for循环来比较使用max_leaf_nodes的不同值构建的模型的准确性。

python
# compare MAE with differing values of max_leaf_nodes
for max_leaf_nodes in [5, 50, 500, 5000]:
    my_mae = get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y)
    print("Max leaf nodes: %d  \t\t Mean Absolute Error:  %d" %(max_leaf_nodes, my_mae))
plaintext
Max leaf nodes: 5  		     Mean Absolute Error:  347380
Max leaf nodes: 50  		 Mean Absolute Error:  258171
Max leaf nodes: 500  		 Mean Absolute Error:  243495
Max leaf nodes: 5000  		 Mean Absolute Error:  254983

在列出的选项中,500是叶子的最优数量。

Conclusion

结论是:模型可能会有以下两种情况:

  • 过度拟合:捕捉未来不会再出现的虚假模式,导致预测不太准确,或者
  • 拟合不足:未能捕捉相关模式,再次导致预测不太准确。

我们使用模型训练中没有使用的验证数据来衡量候选模型的准确性。这让我们可以尝试许多候选模型,并保留最好的模型。

Exercise

Recap

回顾一下本课程之前书写的代码

python
# Code you have previously used to load data
import pandas as pd
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor


# Path of the file to read
iowa_file_path = '../input/home-data-for-ml-course/train.csv'

home_data = pd.read_csv(iowa_file_path)
# Create target object and call it y
y = home_data.SalePrice
# Create X
features = ['LotArea', 'YearBuilt', '1stFlrSF', '2ndFlrSF', 'FullBath', 'BedroomAbvGr', 'TotRmsAbvGrd']
X = home_data[features]

# Split into validation and training data
train_X, val_X, train_y, val_y = train_test_split(X, y, random_state=1)

# Specify Model
iowa_model = DecisionTreeRegressor(random_state=1)
# Fit Model
iowa_model.fit(train_X, train_y)

# Make validation predictions and calculate mean absolute error
val_predictions = iowa_model.predict(val_X)
val_mae = mean_absolute_error(val_predictions, val_y)
print("Validation MAE: {:,.0f}".format(val_mae))

# Set up code checking
from learntools.core import binder
binder.bind(globals())
from learntools.machine_learning.ex5 import *
print("\nSetup complete")

你可以自己编写函数’ get_mae ‘。目前,我们将提供它。这和你在上一课读到的函数是一样的。运行下面的单元格。

python
def get_mae(max_leaf_nodes, train_X, val_X, train_y, val_y):
    model = DecisionTreeRegressor(max_leaf_nodes=max_leaf_nodes, random_state=0)
    model.fit(train_X, train_y)
    preds_val = model.predict(val_X)
    mae = mean_absolute_error(val_y, preds_val)
    return(mae)

Step 1: Compare Different Tree Sizes

编写一个循环,从一组可能的值中为max_leaf_nodes尝试以下值。

对max_leaf_nodes的每个值调用get_mae函数。以一种允许您选择max_leaf_nodes的值的方式存储输出,该值给出数据的最准确模型。

python
candidate_max_leaf_nodes = [5, 25, 50, 100, 250, 500]
# Write loop to find the ideal tree size from candidate_max_leaf_nodes
my_mae = {leaf_size:get_mae(leaf_size,train_X,val_X,train_y,val_y) for leaf_size in candidate_max_leaf_nodes}
# Store the best value of max_leaf_nodes (it will be either 5, 25, 50, 100, 250 or 500)
best_tree_size = min(my_mae,key = my_mae.get)

# Check your answer
step_1.check()

Step 2: Fit Model Using All Data

你知道最好的树的大小。如果您打算在实践中部署此模型,则可以通过使用所有数据并保持该树的大小来使其更加准确。也就是说,既然您已经做出了所有的建模决策,就不需要再提供验证数据了。

python
# Fill in argument to make optimal size and uncomment
final_model = DecisionTreeRegressor(max_leaf_nodes=best_tree_size,random_state=1)

# fit the final model and uncomment the next two lines
final_model.fit(X, y)

# Check your answer
step_2.check()